package zaplog

import (
	"fmt"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
)

type Config struct {
	FileLoggingEnabled bool
	EncodeLogsAsJson   bool
	Directory          string
	Filename           string
	MaxSize            int // 每个日志文件保存的最大尺寸 单位：M
	MaxBackups         int // 日志文件最多保存多少个备份
	MaxAge             int // 文件最多保存多少天
}

func init() {
	config := Config{
		FileLoggingEnabled: true,
		EncodeLogsAsJson:   true,
		Filename:           "kee.log",
		Directory:          "/data/log/",
		MaxSize:            200,
		MaxBackups:         30,
		MaxAge:             30,
	}
	Configurable(config)
}

var DefaultZapLogger *zap.Logger

func Configurable(config Config) {
	var writes []zapcore.WriteSyncer

	// 日志输出在控制台或文件
	if config.FileLoggingEnabled {
		writes = append(writes, newRollingFile(config))
	} else {
		writes = append(writes, os.Stdout)
	}
	DefaultZapLogger = NewZapLogger(config.EncodeLogsAsJson, zapcore.NewMultiWriteSyncer(writes...))
	zap.RedirectStdLog(DefaultZapLogger)
}

func NewZapLogger(encodeLogsAsJson bool, output zapcore.WriteSyncer) *zap.Logger {
	cfg := zapcore.EncoderConfig{
		MessageKey:     "msg",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		TimeKey:        "ts",
		StacktraceKey:  "trace",
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	}

	// 编码器配置
	encoder := zapcore.NewConsoleEncoder(cfg)
	if encodeLogsAsJson {
		encoder = zapcore.NewJSONEncoder(cfg)
	}
	core := zapcore.NewCore(encoder, output, zap.NewAtomicLevel())
	return zap.New(core, zap.AddCaller())
}

func newRollingFile(config Config) zapcore.WriteSyncer {
	if err := os.MkdirAll(config.Directory, 0775); err != nil {
		fmt.Println("create dir failed ", err)
		return nil
	}
	return zapcore.AddSync(&lumberjack.Logger{
		Filename:   config.Directory + config.Filename, // 日志文件路径
		MaxSize:    config.MaxSize,                     // 每个日志文件保存的最大尺寸 单位：M
		MaxBackups: config.MaxBackups,                  // 日志文件最多保存多少个备份
		MaxAge:     config.MaxAge,                      // 文件最多保存多少天
		//Compress:   true,                            // 是否压缩
	})

}

func Info(msg string, fields ...zap.Field) {
	DefaultZapLogger.Info(msg, fields...)
}

func Debug(msg string, fields ...zap.Field) {
	DefaultZapLogger.Debug(msg, fields...)
}

func Fatal(msg string, fields ...zap.Field) {
	DefaultZapLogger.Fatal(msg, fields...)
}

func Error(msg string, fields ...zap.Field) {
	DefaultZapLogger.Error(msg, fields...)
}

func Warn(msg string, fields ...zap.Field) {
	DefaultZapLogger.Warn(msg, fields...)
}

func Trace(id string) *zap.Logger {
	return DefaultZapLogger.With(zap.String("id", id))
}

func Logger() *zap.Logger {
	return DefaultZapLogger
}
